`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2023/12/10 15:13:47
// Design Name:
// Module Name: testCPU
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////


module testCPU(

  );

  logic clk;
  logic [15:0] instruction;
  logic [15:0] inM;
  logic rst;

  logic [15:0]outM;
  logic writeM;
  logic [14:0]addressM;
  logic [14:0]pc;


  CPU cpu(clk, rst, inM, instruction, outM, writeM, addressM, pc);

  initial
  begin
    clk = 1;
    forever
    begin
      #10;
      clk = ~clk;
    end
  end

  initial
  begin
    rst = 0;
    repeat(1) @(posedge clk);
    rst = 1;
    inM = 0;

    instruction = 16'b0011000000111001; // @12345
    repeat(1) @(posedge clk);
    instruction = 16'b1110110000010000; // D=A
    repeat(1) @(posedge clk);
    instruction=  16'b0101101110100000; // @23456
    repeat(1) @(posedge clk);
    instruction=  16'b1110000111110000; // AD=A-D
    repeat(1) @(posedge clk);

    assert(outM === 'd11111) else
            $error("23456 - 12345 failed");

    instruction= 16'b0000001111101011; // @1003
    repeat(1) @(posedge clk);
    instruction= 16'b1110001100001000; // M=D
    repeat(1) @(posedge clk);

    assert(writeM === 1'b1) else
            $error("writeM failed");
    assert(addressM === 'd1003) else
            $error("addressM failed");
    assert(pc === 6) else
            $error("pc == 6 failed");

    instruction= 16'b0000001111100111; // @999
    repeat(1) @(posedge clk);
    inM = 'd9999;
    instruction= 16'b1111110111100000; // A=M+1
    repeat(1) @(posedge clk);
    assert(outM === 'd10000) else
            $error("9999 + 1 failed");

    instruction = 16'b0000000001001000;  // @72
    repeat(1) @(posedge clk);
    instruction = 16'b1110110000010000; // D = A
    repeat(1) @(posedge clk);
    instruction = 16'b0100000000000001; // @16385
    repeat(1) @(posedge clk);
    instruction = 16'b1110001100001000; // M = D
    repeat(1) @(posedge clk);
    assert (addressM === 'h4001) else
             $error("write 48 Address failed");
    assert (outM === 'h48) else
             $error("write 48 Data failed");
  end

endmodule
